package com.example.javapoet.demo.scenarios;

import com.squareup.javapoet.*;
import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * JavaPoet场景示例 - 生成ORM映射代码
 */
public class OrmMappingGeneration {

    public static void main(String[] args) {
        // 生成实体类
        generateEntityClass();
        
        // 生成Repository接口
        generateRepositoryInterface();
        
        // 生成Repository实现类
        generateRepositoryImplClass();
    }

    /**
     * 生成实体类
     */
    public static void generateEntityClass() {
        // 创建字段
        FieldSpec idField = FieldSpec.builder(long.class, "id")
                .addModifiers(Modifier.PRIVATE)
                .addAnnotation(AnnotationSpec.builder(ClassName.get("javax.persistence", "Id"))
                        .build())
                .addAnnotation(AnnotationSpec.builder(ClassName.get("javax.persistence", "GeneratedValue"))
                        .addMember("strategy", "$T.IDENTITY", ClassName.get("javax.persistence", "GenerationType"))
                        .build())
                .build();
        
        FieldSpec nameField = FieldSpec.builder(String.class, "name")
                .addModifiers(Modifier.PRIVATE)
                .addAnnotation(AnnotationSpec.builder(ClassName.get("javax.persistence", "Column"))
                        .addMember("name", "$S", "user_name")
                        .addMember("nullable", "$L", false)
                        .addMember("length", "$L", 100)
                        .build())
                .build();
        
        FieldSpec emailField = FieldSpec.builder(String.class, "email")
                .addModifiers(Modifier.PRIVATE)
                .addAnnotation(AnnotationSpec.builder(ClassName.get("javax.persistence", "Column"))
                        .addMember("unique", "$L", true)
                        .addMember("nullable", "$L", false)
                        .build())
                .build();
        
        FieldSpec ageField = FieldSpec.builder(int.class, "age")
                .addModifiers(Modifier.PRIVATE)
                .addAnnotation(AnnotationSpec.builder(ClassName.get("javax.persistence", "Column"))
                        .addMember("name", "$S", "user_age")
                        .build())
                .build();
        
        // 创建构造函数
        MethodSpec defaultConstructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .build();
        
        MethodSpec fullConstructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .addParameter(long.class, "id")
                .addParameter(String.class, "name")
                .addParameter(String.class, "email")
                .addParameter(int.class, "age")
                .addStatement("this.id = id")
                .addStatement("this.name = name")
                .addStatement("this.email = email")
                .addStatement("this.age = age")
                .build();
        
        // 创建getter和setter方法
        MethodSpec getIdMethod = MethodSpec.methodBuilder("getId")
                .addModifiers(Modifier.PUBLIC)
                .returns(long.class)
                .addStatement("return id")
                .build();
        
        MethodSpec setIdMethod = MethodSpec.methodBuilder("setId")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(long.class, "id")
                .addStatement("this.id = id")
                .build();
        
        MethodSpec getNameMethod = MethodSpec.methodBuilder("getName")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return name")
                .build();
        
        MethodSpec setNameMethod = MethodSpec.methodBuilder("setName")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(String.class, "name")
                .addStatement("this.name = name")
                .build();
        
        MethodSpec getEmailMethod = MethodSpec.methodBuilder("getEmail")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return email")
                .build();
        
        MethodSpec setEmailMethod = MethodSpec.methodBuilder("setEmail")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(String.class, "email")
                .addStatement("this.email = email")
                .build();
        
        MethodSpec getAgeMethod = MethodSpec.methodBuilder("getAge")
                .addModifiers(Modifier.PUBLIC)
                .returns(int.class)
                .addStatement("return age")
                .build();
        
        MethodSpec setAgeMethod = MethodSpec.methodBuilder("setAge")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(int.class, "age")
                .addStatement("this.age = age")
                .build();
        
        // 创建toString方法
        MethodSpec toStringMethod = MethodSpec.methodBuilder("toString")
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return $S + id + $S + name + $S + email + $S + age + $S", 
                        "User{id=", ", name='", "', email='", "', age=", "}")
                .build();
        
        // 创建类
        TypeSpec userClass = TypeSpec.classBuilder("User")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(ClassName.get("javax.persistence", "Entity"))
                        .addMember("name", "$S", "User")
                        .build())
                .addAnnotation(AnnotationSpec.builder(ClassName.get("javax.persistence", "Table"))
                        .addMember("name", "$S", "users")
                        .build())
                .addField(idField)
                .addField(nameField)
                .addField(emailField)
                .addField(ageField)
                .addMethod(defaultConstructor)
                .addMethod(fullConstructor)
                .addMethod(getIdMethod)
                .addMethod(setIdMethod)
                .addMethod(getNameMethod)
                .addMethod(setNameMethod)
                .addMethod(getEmailMethod)
                .addMethod(setEmailMethod)
                .addMethod(getAgeMethod)
                .addMethod(setAgeMethod)
                .addMethod(toStringMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.orm.entity", userClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("生成User实体类:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成User.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成Repository接口
     */
    public static void generateRepositoryInterface() {
        // 创建方法
        MethodSpec findByNameMethod = MethodSpec.methodBuilder("findByName")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(ParameterizedTypeName.get(
                        ClassName.get("java.util", "List"),
                        ClassName.get("com.example.orm.entity", "User")))
                .addParameter(String.class, "name")
                .addAnnotation(AnnotationSpec.builder(ClassName.get("org.springframework.data.jpa.repository", "Query"))
                        .addMember("value", "$S", "SELECT u FROM User u WHERE u.name LIKE :name")
                        .build())
                .build();
        
        MethodSpec findByEmailMethod = MethodSpec.methodBuilder("findByEmail")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(ClassName.get("com.example.orm.entity", "User"))
                .addParameter(String.class, "email")
                .build();
        
        MethodSpec findByAgeBetweenMethod = MethodSpec.methodBuilder("findByAgeBetween")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(ParameterizedTypeName.get(
                        ClassName.get("java.util", "List"),
                        ClassName.get("com.example.orm.entity", "User")))
                .addParameter(int.class, "minAge")
                .addParameter(int.class, "maxAge")
                .build();
        
        // 创建接口
        TypeSpec userRepositoryInterface = TypeSpec.interfaceBuilder("UserRepository")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(ClassName.get("org.springframework.stereotype", "Repository"))
                .addSuperinterface(ParameterizedTypeName.get(
                        ClassName.get("org.springframework.data.jpa.repository", "JpaRepository"),
                        ClassName.get("com.example.orm.entity", "User"),
                        ClassName.get(Long.class)))
                .addMethod(findByNameMethod)
                .addMethod(findByEmailMethod)
                .addMethod(findByAgeBetweenMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.orm.repository", userRepositoryInterface)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成UserRepository接口:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成UserRepository.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成Repository实现类
     */
    public static void generateRepositoryImplClass() {
        // 创建字段
        FieldSpec entityManagerField = FieldSpec.builder(
                ClassName.get("javax.persistence", "EntityManager"), 
                "entityManager")
                .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
                .build();
        
        // 创建构造函数
        MethodSpec constructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .addParameter(ClassName.get("javax.persistence", "EntityManager"), "entityManager")
                .addStatement("this.entityManager = entityManager")
                .build();
        
        // 创建自定义查询方法
        MethodSpec findActiveUsersMethod = MethodSpec.methodBuilder("findActiveUsers")
                .addModifiers(Modifier.PUBLIC)
                .returns(ParameterizedTypeName.get(
                        ClassName.get("java.util", "List"),
                        ClassName.get("com.example.orm.entity", "User")))
                .addStatement("$T query = entityManager.createQuery($S, $T.class)", 
                        ClassName.get("javax.persistence", "TypedQuery"),
                        "SELECT u FROM User u WHERE u.status = 'ACTIVE'",
                        ClassName.get("com.example.orm.entity", "User"))
                .addStatement("return query.getResultList()")
                .build();
        
        MethodSpec countByAgeMethod = MethodSpec.methodBuilder("countByAge")
                .addModifiers(Modifier.PUBLIC)
                .returns(long.class)
                .addParameter(int.class, "age")
                .addStatement("$T query = entityManager.createQuery($S, $T.class)", 
                        ClassName.get("javax.persistence", "TypedQuery"),
                        "SELECT COUNT(u) FROM User u WHERE u.age = :age",
                        Long.class)
                .addStatement("query.setParameter($S, age)", "age")
                .addStatement("return query.getSingleResult()")
                .build();
        
        // 创建类
        TypeSpec userRepositoryImplClass = TypeSpec.classBuilder("UserRepositoryImpl")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(ClassName.get("org.springframework.stereotype", "Repository"))
                .addField(entityManagerField)
                .addMethod(constructor)
                .addMethod(findActiveUsersMethod)
                .addMethod(countByAgeMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.orm.repository.impl", userRepositoryImplClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成UserRepositoryImpl类:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成UserRepositoryImpl.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}